package cn.hollis.nft.turbo.order.domain.service;

import cn.hollis.nft.turbo.api.order.constant.OrderErrorCode;
import cn.hollis.nft.turbo.api.order.request.BaseOrderUpdateRequest;
import cn.hollis.nft.turbo.api.order.request.OrderPayRequest;
import cn.hollis.nft.turbo.api.order.response.OrderResponse;
import cn.hollis.nft.turbo.base.exception.BizException;
import cn.hollis.nft.turbo.base.exception.RepoErrorCode;
import cn.hollis.nft.turbo.order.domain.entity.TradeOrder;
import cn.hollis.nft.turbo.order.domain.entity.TradeOrderStream;
import cn.hollis.nft.turbo.order.domain.exception.OrderException;
import cn.hollis.nft.turbo.order.infrastructure.mapper.OrderMapper;
import cn.hollis.nft.turbo.order.infrastructure.mapper.OrderStreamMapper;
import cn.hutool.core.lang.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.function.Function;

import static cn.hollis.nft.turbo.api.order.constant.OrderErrorCode.ORDER_NOT_EXIST;

@Component
public class HandleWithTranImpl implements Function<BaseOrderUpdateRequest,OrderResponse>{

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderStreamMapper orderStreamMapper;
    @Autowired
    protected TransactionTemplate transactionTemplate;
    @Override
    public OrderResponse apply(BaseOrderUpdateRequest orderRequest) {
        TradeOrder existOrder = orderMapper.selectByOrderId(orderRequest.getOrderId());
        if (existOrder == null) {
            throw new OrderException(ORDER_NOT_EXIST);
        }

//        if (!hasPermission(existOrder, orderRequest.getOrderEvent(), orderRequest.getOperator(), orderRequest.getOperatorType())) {
//            throw new OrderException(PERMISSION_DENIED);
//        }

        TradeOrderStream existStream = orderStreamMapper.selectByIdentifier(orderRequest.getIdentifier(), orderRequest.getOrderEvent().name(), orderRequest.getOrderId());
        if (existStream != null) {
            return new OrderResponse.OrderResponseBuilder().orderId(existStream.getOrderId()).streamId(existStream.getId().toString()).buildDuplicated();
        }
        existOrder.pay((OrderPayRequest) orderRequest);
        //开启事务
        return transactionTemplate.execute(transactionStatus -> {

            boolean result = orderMapper.updateByOrderId(existOrder) == 1;
            Assert.isTrue(result, () -> new OrderException(OrderErrorCode.UPDATE_ORDER_FAILED));

            TradeOrderStream orderStream = new TradeOrderStream(existOrder, orderRequest.getOrderEvent(), orderRequest.getIdentifier());
            result = orderStreamMapper.insert(orderStream) == 1;
            Assert.isTrue(result, () -> new BizException(RepoErrorCode.INSERT_FAILED));

            return new OrderResponse.OrderResponseBuilder().orderId(orderStream.getOrderId()).streamId(String.valueOf(orderStream.getId())).buildSuccess();
        });
    }
}
